#include "Button.h"
#include "../Script.h"
#include "Text.h"
#include "Picture.h"

//Stupid linker
template<class T> T& max(T& a, T& b)	{	if(a < b)	return b;	return a;	}

void Button::executeCommand() {
// Send the command through the script processor
	Script::process(command.c_str());
}

Button::Button(const std::string& cmd)
: Object()
, text(NULL)
, pic(NULL)
, command(cmd)
{}

Button::~Button() {
	if(text != NULL) {
		delete text;
		text = NULL;
	}
	if(pic != NULL) {
		delete pic;
		pic = NULL;
	}
}
	
void Button::draw(unsigned long) {
//How nice and simple to draw
	glColor4d(color.r,color.g,color.b, color.a);
	glBegin(GL_QUADS);
		glVertex3d(drawPos.x, drawPos.y, drawPos.z);
		glVertex3d(drawPos.x + dimensions.x, drawPos.y, drawPos.z);
		glVertex3d(drawPos.x + dimensions.x, drawPos.y + dimensions.y, drawPos.z);
		glVertex3d(drawPos.x, drawPos.y + dimensions.y, drawPos.z);
	glEnd();
}
	
void Button::onLeftClick() {
	executeCommand();
}
void Button::onKeyPress() {
	executeCommand();
}
void Button::onRollOver() {
}

void Button::resize() {
	if(text != NULL && pic == NULL)
		text->getDimensions(&dimensions.x, &dimensions.y);	//if we have text and no picture
	else if(pic != NULL) {
		pic->getDimensions(&dimensions.x, &dimensions.y);		//if we have a picture
		if(text != NULL) {
			double W, H;								//if we have picture and text
			text->getDimensions(&W, &H);
			dimensions.x = max(dimensions.x, W);
			dimensions.y = max(dimensions.y, H);
		}
	}
}

void Button::setText(const std::string& str) {
	if(text != NULL) {
		text->setText(str);
		resize();
	}
}

void Button::setFont(const std::string& fnt) {
	if(text != NULL) {
		text->setFont(fnt);
		resize();
	}
}

void Button::setSize(int size) {
	if(text != NULL) {
		text->setSize(size);
		resize();
	}
}

void Button::enable() {
	Object::enable();
	if(text != NULL)	text->enable();
	if(pic != NULL)	pic->enable();
}

void Button::disable() {
	Object::disable();
	if(text != NULL)	text->disable();
	if(pic != NULL)	text->disable();
}

void Button::onRealign(float minX, float maxX, float minY, float maxY) {
	switch(horizAlignment) {
	case LEFT:
		drawPos.x = padding;
		break;
	case RIGHT:
		drawPos.x = maxX - dimensions.x - padding;
		break;
	case HORIZ_MIDDLE:
		drawPos.x = (maxX + minX - dimensions.x) / 2.0;
		break;
	case ABSOLUTE:
	default:
		break;
	}
	switch(vertAlignment) {
	case TOP:
		drawPos.y = maxY - dimensions.y - padding;
		break;
	case BOTTOM:
		drawPos.y = padding;
		break;
	case VERT_MIDDLE:
		drawPos.y = (maxY + minY - dimensions.y) / 2.0;
		break;
	case ABSOLUTE:
	default:
		break;
	}
	
	//Tell our child to realign in accordance to our position and size
	if(text != NULL)
		text->onRealign(drawPos.x, drawPos.x + dimensions.x, drawPos.y , drawPos.y + dimensions.y);
	else if(pic != NULL)
		pic->onRealign(drawPos.x, drawPos.x + dimensions.x, drawPos.y , drawPos.y + dimensions.y);
}

void Button::loadFromXML(ticpp::Node* node, int Z, Frame* f) {
	using namespace ticpp;
	Object::loadFromXML(node, Z, f);
	
	Element* elem = node->ToElement();
	elem->GetAttribute("command", &command, false);
	
	Node *child = NULL;
	while( (child = node->IterateChildren( child )) != NULL) {
		std::string val;
		child->GetValue(&val);
		//Allow only Text or Picture to be children of button
		if(val == "Text" && text == NULL) {
			text = new TextObject();
			text->loadFromXML(child, --Z, f);
		} else if (val == "Picture" && pic == NULL) {
			pic = new Picture();
			pic->loadFromXML(child, --Z, f);
		} else
			throw Exception("Child(ren) of Button were too numerous or of incorrect type");
	}
	
	resize();
}

